<?php

namespace app\api\model;

use app\api\constant\StatusConst;
use think\Exception;
use think\Model;

class BaseModel extends Model
{
    protected $pk = 'id';
    private $versionField = "lock_version";

    protected $APP_URL = 'http://guizhou.shsm8.cn';

    /**
     * 获取单个字段值
     * @param $where
     * @param string|null $field
     * @return float|mixed|string
     */
    public static function getValue($where, ?string $field = '')
    {
        $pk = static::getPk();
        return static::where($where)->value($field ?: $pk);
    }

    /**
     * 获取某些条件总数
     * @param array $where
     * @return int|string
     * @throws Exception
     */
    public static function getCount(array $where)
    {
        return static::where($where)->count();
    }

    /**
     * 软删除
     * @param array $where
     * @return BaseModel
     */
    public static function del(array $where): BaseModel
    {
        return static::where($where)->update([
            'is_del' => StatusConst::FORBIDDEN
        ]);
    }

    /**
     * 获取一条数据
     * @param $id
     * @param array|null $field
     * @param array|null $with
     * @return array|bool|\PDOStatement|string|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getOne($id, ?array $field = [], ?array $with = [])
    {
        $model = new static();
        if (is_array($id)) {
            $where = $id;
        } else {
            $where = [$model->getPk() => $id];
        }
        return static::getModel()->where($where)->field($field ?? ['*'])->find();
    }

    /**
     * 新增数据
     * @param array $data
     * @return void
     * @throws Exception
     */
    public static function modelCreate(array $data)
    {
        try {
            static::create($data, true);
        } catch (Exception $e) {
            throw new Exception("新增数据失败");
        }
    }

    /**
     * 乐观锁更新操作
     * @param $save_data
     * @param $edit_pk
     * @param $version_field
     * @return int
     * @throws Exception
     */
    public function cas($save_data, $edit_pk = "", $version_field = ""): int
    {
        if (empty($version_field)) {
            $version_field = $this->versionField ?? "edit_version";
        }
        if (empty($edit_pk)) {
            $edit_pk = isset($this->editPk) ? $this->editPk : $this->getPk();
        }
        //判断PK字段是否存在
        if (!isset($save_data[$edit_pk]) || !isset($save_data[$version_field])) {
            return 0;

            throw new \think\Exception("参数缺失");
        } else {
            //设置升级检索条件 PK和版本号
            $map[$edit_pk] = $save_data[$edit_pk];
            $map[$version_field] = $save_data[$version_field];
            //剔除PK
            unset($save_data[$edit_pk]);
        }

        try {
            //检测版本字段
            if ($this->hasColumn($version_field)) {
                return 0;

                throw new Exception("乐观锁版本字段[$version_field]不存在");
            }
            $original_data = $this->where($map)->find();

            if (empty($original_data)) {
                return 0;

                throw new Exception("此条信息已经变动了,请重新操作!");
            }

            foreach ($save_data as $item => $value) {
                if (isset($original_data[$item])) {
                    //修改的数值不变时候 剔除
                    if ($original_data[$item] == $value) {
                        unset($save_data[$item]);
                    } elseif ($item != $version_field) {
                        unset($original_data[$item]);
                    }
                } else {
                    //修改的字段不存在 剔除
                    unset($save_data[$item]);
                }
            }

            if (empty($save_data)) {
                return 0;

                throw new Exception("修改的数值无变化");
            }
            //版本号升级
            $save_data[$version_field] = (int)$original_data[$version_field] + 1;
            if (1 != $this->allowField(true)->save($save_data, $map)) {
                return 0;
                throw new Exception("修改信息出错:" . $this->getError());
            }
            return 1;
            //记录修改日志
        } catch (Exception $e) {
            throw new \think\Exception("更新失败" . $e->getMessage());
//            return self::showReturnCodeWithOutData(1003,$msg);
        }
    }
}